﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.Design

Namespace DotNetNuke.Modules.ActiveForums.Controls
    <DefaultProperty("Text"), Designer("DotNetNuke.Modules.ActiveForums.Controls.ActiveGridDesigner"), ToolboxData("<{0}:activegrid runat=server><headertemplate></headertemplate><itemtemplate></itemtemplate><footertemplate></footertemplate></{0}:activegrid>")> _
    Public Class ActiveGrid
        Inherits CompositeControl

#Region "Declarations"
        Private lit As Literal
        Private div As HtmlControls.HtmlGenericControl
        Protected WithEvents cb As Callback
        Private _ItemTemplate As ItemTemplateContents
        Private _HeaderTemplate As ItemTemplateContents
        Private _FooterTemplate As ItemTemplateContents
        Private _datasource As IDataReader
        Private _dataView As DataView
        Private _rowDelimiter As String = "^"
        Private _colDelimiter As String = "|"
        Private _PageSize As Integer = 10
        Private _ItemStyle As String = "amdatarow"
        Private _AltItemStyle As String = "amrowalternating"
        Private _SelectedStyle As String = "amrowselected"
        Private _ShowPager As Boolean = True
        Private _PagerText As String = "Page {0} of {1}"
        Private _ImagePath As String = ""
        Private _PagerPages As Integer = 10
        Private _DefaultColumn As String
        Private _DefaultParams As String = ""
        Private _DefaultSort As Sort = Sort.Descending
        Private _CssPagerInfo As String = "ampagerinfo"
        Private _CssPagerItem As String = "amPageritem"
        Private _CssPagerItem2 As String = "ampagertem2"
        Private _CssPagerCurrentNumber As String = "ampagernumber_current"
        Private _CssPagerNumber As String = "ampagernumber"
        Private _SpacerImage As String = ""
        Private _AscImage As String = ""
        Private _DescImage As String = ""
        Private _LoadOnRender As Boolean = True
        Private _OnComplete As String
        Enum Sort
            Ascending
            Descending
        End Enum
        Public Event ItemBound As ItemBoundEventHandler
        Delegate Sub ItemBoundEventHandler(ByVal sender As Object, ByVal e As ItemBoundEventArgs)
#End Region

#Region "Properties"
        ''' <summary>
        ''' Item Template - Must include a table row.
        ''' </summary>
        <Description("Initial content to render."), DefaultValue(Nothing, ""), Browsable(False), NotifyParentProperty(True), PersistenceMode(PersistenceMode.InnerProperty)> _
        Public Property ItemTemplate() As ItemTemplateContents
            Get
                Return _ItemTemplate
            End Get
            Set(ByVal Value As ItemTemplateContents)
                _ItemTemplate = Value
            End Set
        End Property
        ''' <summary>
        ''' Header Template - Must include opening table tag and first table row.
        ''' </summary>
        ''' , DesignerSerializationVisibility(DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty)
        <Description("Initial content to render."), DefaultValue(Nothing, ""), Browsable(False), NotifyParentProperty(True), PersistenceMode(PersistenceMode.InnerProperty)> _
        Public Property HeaderTemplate() As ItemTemplateContents
            Get
                Return _HeaderTemplate
            End Get
            Set(ByVal Value As ItemTemplateContents)
                _HeaderTemplate = Value
            End Set
        End Property
        ''' <summary>
        ''' Footer Template - Must include closing table tag.
        ''' </summary>
        ''' , DesignerSerializationVisibility(DesignerSerializationVisibility.Content), PersistenceMode(PersistenceMode.InnerProperty)
        <Description("Initial content to render."), DefaultValue(Nothing, ""), Browsable(False), NotifyParentProperty(True), PersistenceMode(PersistenceMode.InnerProperty)> _
        Public Property FooterTemplate() As ItemTemplateContents
            Get
                Return _FooterTemplate
            End Get
            Set(ByVal Value As ItemTemplateContents)
                _FooterTemplate = Value
            End Set
        End Property
        ''' <summary>
        ''' String delimiter to separate row data in callback.  Ensure none of your data will include this string.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property RowDelimiter() As String
            Get
                Return _rowDelimiter
            End Get

            Set(ByVal Value As String)
                _rowDelimiter = Value
            End Set
        End Property
        ''' <summary>
        ''' String delimiter to separate column data in callback.  Ensure none of your data will include this string.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property ColDelimiter() As String
            Get
                Return _colDelimiter
            End Get

            Set(ByVal Value As String)
                _colDelimiter = Value
            End Set
        End Property
        ''' <summary>
        ''' Must be an IDataReader.  First SELECT is total row count.  Second is the data we display.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property Datasource() As IDataReader
            Get
                Return _datasource
            End Get

            Set(ByVal Value As IDataReader)
                _datasource = Value
            End Set
        End Property
        ''' <summary>
        ''' Number of records to show per page.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property PageSize() As Integer
            Get
                Return _PageSize
            End Get
            Set(ByVal Value As Integer)
                _PageSize = Value
            End Set
        End Property
        ''' <summary>
        ''' CSS class name added to Item Template table row.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property ItemStyle() As String
            Get
                Return _ItemStyle
            End Get

            Set(ByVal Value As String)
                _ItemStyle = Value
            End Set
        End Property
        ''' <summary>
        ''' CSS class name added to Item Template every other table row.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property AltItemStyle() As String
            Get
                Return _AltItemStyle
            End Get

            Set(ByVal Value As String)
                _AltItemStyle = Value
            End Set
        End Property
        ''' <summary>
        ''' CSS class name added to Item Template table row when moused over.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property SelectedStyle() As String
            Get
                Return _SelectedStyle
            End Get

            Set(ByVal Value As String)
                _SelectedStyle = Value
            End Set
        End Property
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property ShowPager() As Boolean
            Get
                Return _ShowPager
            End Get

            Set(ByVal Value As Boolean)
                _ShowPager = Value
            End Set
        End Property
        ''' <summary>
        ''' Fires a callback immediately after grid is rendered.  True by default.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property LoadOnRender() As Boolean
            Get
                Return _LoadOnRender
            End Get

            Set(ByVal Value As Boolean)
                _LoadOnRender = Value
            End Set
        End Property
        ''' <summary>
        ''' "Page {0} of {1}".
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property PagerText() As String
            Get
                Return _PagerText
            End Get

            Set(ByVal Value As String)
                _PagerText = Value
            End Set
        End Property
        ''' <summary>
        ''' Path to directory for Pager Images.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property ImagePath() As String
            Get
                Return _ImagePath
            End Get

            Set(ByVal Value As String)
                _ImagePath = Value
            End Set
        End Property
        ''' <summary>
        ''' Number of pages.
        ''' </summary>
        <Bindable(True), Category("Appearance"), DefaultValue(""), Localizable(True)> Property PagerPages() As Integer
            Get
                Return _PagerPages
            End Get

            Set(ByVal Value As Integer)
                _PagerPages = Value
            End Set
        End Property
        ''' <summary>
        ''' Default Sort for first load.  Default Descending.
        ''' </summary>
        Property DefaultSort() As Sort
            Get
                Return _DefaultSort
            End Get
            Set(ByVal value As Sort)
                _DefaultSort = value
            End Set
        End Property
        ''' <summary>
        ''' Default Column to sort by.
        ''' </summary>
        Property DefaultColumn() As String
            Get
                Return _DefaultColumn
            End Get
            Set(ByVal value As String)
                _DefaultColumn = value
            End Set
        End Property
        ''' <summary>
        ''' Default Parameters to pass in to the callback on first load.
        ''' </summary>
        Property DefaultParams() As String
            Get
                Return _DefaultParams
            End Get
            Set(ByVal value As String)
                _DefaultParams = value
            End Set
        End Property
        ''' <summary>
        ''' CSS class for the pager info.
        ''' </summary>
        Property CssPagerInfo() As String
            Get
                Return _CssPagerInfo
            End Get
            Set(ByVal value As String)
                _CssPagerInfo = value
            End Set
        End Property
        ''' <summary>
        ''' CSS class for every page number except the first.
        ''' </summary>
        Property CssPagerItem() As String
            Get
                Return _CssPagerItem
            End Get
            Set(ByVal value As String)
                _CssPagerItem = value
            End Set
        End Property
        ''' <summary>
        ''' CSS class for the first page number.
        ''' </summary>
        Property CssPagerItem2() As String
            Get
                Return _CssPagerItem2
            End Get
            Set(ByVal value As String)
                _CssPagerItem2 = value
            End Set
        End Property
        ''' <summary>
        ''' CSS class for the current page.
        ''' </summary>
        Property CssPagerCurrentNumber() As String
            Get
                Return _CssPagerCurrentNumber
            End Get
            Set(ByVal value As String)
                _CssPagerCurrentNumber = value
            End Set
        End Property
        ''' <summary>
        ''' CSS class for the page numbers.
        ''' </summary>
        Property CssPagerNumber() As String
            Get
                Return _CssPagerNumber
            End Get
            Set(ByVal value As String)
                _CssPagerNumber = value
            End Set
        End Property
        ''' <summary>
        ''' URL to spacer image if not using the built in one.
        ''' </summary>
        Property SpacerImage() As String
            Get
                Return _SpacerImage
            End Get
            Set(ByVal value As String)
                _SpacerImage = value
            End Set
        End Property
        ''' <summary>
        ''' URL to the Ascending sort image if not using the built in one.
        ''' </summary>
        Property AscImage() As String
            Get
                Return _AscImage
            End Get
            Set(ByVal value As String)
                _AscImage = value
            End Set
        End Property
        ''' <summary>
        ''' URL to the Descending sort image if not using the built in one.
        ''' </summary>
        Property DescImage() As String
            Get
                Return _DescImage
            End Get
            Set(ByVal value As String)
                _DescImage = value
            End Set
        End Property
        Property OnComplete() As String
            Get
                Return cb.OnCallbackComplete
            End Get
            Set(ByVal value As String)
                EnsureChildControls()
                cb.OnCallbackComplete = value
            End Set
        End Property
#End Region

#Region "Subs/Functions"
        Protected Overrides Sub CreateChildControls()
            div = New HtmlControls.HtmlGenericControl
            div.ID = Me.ClientID
            lit = New Literal
            lit.ID = "data_" & Me.ClientID
            cb = New Callback
            If HttpContext.Current.Request.Params("amagdebug") = "true" Or HttpContext.Current.Request.Params("amdebug") = "true" Then
                cb.Debug = True
            Else
                cb.Debug = False
            End If
            cb.ID = "CB_" & Me.ClientID
            cb.Attributes.Add("style", "display:none;")
            cb.OnCallbackComplete = "function(){" & Me.ClientID & ".Build();}"
            ChildControlsCreated = True
        End Sub
        Protected Overrides Sub Render(ByVal output As HtmlTextWriter)
            Try
                output = New HtmlTextWriter(output, String.Empty)
                Dim sOutput As String = Me.HeaderTemplate.Text & Me.ItemTemplate.Text & Me.FooterTemplate.Text
                div.Controls.Add(Page.ParseControl(sOutput))
                div.RenderControl(output)
                If Me.ShowPager Then
                    output.AddAttribute("id", "pager_" & Me.ClientID)
                    output.RenderBeginTag(HtmlTextWriterTag.Div)
                    output.RenderEndTag()
                End If
                cb.RenderControl(output)
                Dim str As New StringBuilder
                str.Append("<script>")
                str.Append("window." & Me.ClientID & "=new ActiveGrid('" & Me.ClientID & "');")
                If Me.SpacerImage = "" Then
                    Me.SpacerImage = Page.ClientScript.GetWebResourceUrl(Me.GetType, "spacer.gif")
                End If
                If Me.AscImage = "" Then
                    Me.AscImage = Page.ClientScript.GetWebResourceUrl(Me.GetType, "asc.gif")
                End If
                If Me.DescImage = "" Then
                    Me.DescImage = Page.ClientScript.GetWebResourceUrl(Me.GetType, "desc.gif")
                End If
                str.Append("window." & Me.ClientID & ".SpacerImage='" & Me.SpacerImage & "';")
                str.Append("window." & Me.ClientID & ".AscImage='" & Me.AscImage & "';")
                str.Append("window." & Me.ClientID & ".DescImage='" & Me.DescImage & "';")
                str.Append("window." & Me.ClientID & ".SetColumns();")
                If Me.ShowPager Then
                    str.Append("window." & Me.ClientID & ".Pager=document.getElementById('pager_" & Me.ClientID & "');")
                    str.Append("window." & Me.ClientID & ".PagerText='" & Me.PagerText & "';")
                    str.Append("window." & Me.ClientID & ".PagerPages=" & Me.PagerPages & ";")
                    str.Append("window." & Me.ClientID & ".CssPagerInfo='" & Me.CssPagerInfo & "';")
                    str.Append("window." & Me.ClientID & ".CssPagerItem='" & Me.CssPagerItem & "';")
                    str.Append("window." & Me.ClientID & ".CssPagerItem2='" & Me.CssPagerItem2 & "';")
                    str.Append("window." & Me.ClientID & ".CssPagerCurrentNumber='" & Me.CssPagerCurrentNumber & "';")
                    str.Append("window." & Me.ClientID & ".CssPagerNumber='" & Me.CssPagerNumber & "';")
                End If
                str.Append("window." & Me.ClientID & ".Column='" & Me.DefaultColumn & "';")
                If Me.DefaultSort = Sort.Ascending Then
                    str.Append("window." & Me.ClientID & ".Sort='ASC';")
                    str.Append("window." & Me.ClientID & ".DefaultSort='ASC';")
                End If
                str.Append("window." & Me.ClientID & ".Params='" & Me.DefaultParams & "';")
                str.Append("window." & Me.ClientID & ".Width='" & Me.Width.ToString & "';")
                str.Append("window." & Me.ClientID & ".ImagePath='" & Page.ResolveUrl(Me.ImagePath) & "';")
                str.Append("window." & Me.ClientID & ".ItemStyle='" & Me.ItemStyle & "';")
                str.Append("window." & Me.ClientID & ".AltItemStyle='" & Me.AltItemStyle & "';")
                str.Append("window." & Me.ClientID & ".SelectedStyle='" & Me.SelectedStyle & "';")
                str.Append("window." & Me.ClientID & ".PageSize=" & Me.PageSize.ToString & ";")
                str.Append("window." & Me.ClientID & ".RowDelimiter='" & Me.RowDelimiter & "';")
                str.Append("window." & Me.ClientID & ".ColDelimiter='" & Me.ColDelimiter & "';")
                str.Append("window." & Me.ClientID & ".ShowPager=" & Me.ShowPager.ToString.ToLower & ";")
                str.Append("window." & Me.ClientID & ".CB='" & cb.ClientID & "';")
                If Me.LoadOnRender = True Then
                    str.Append("window." & Me.ClientID & ".Callback();")
                End If
                str.Append("</script>")
                output.Write(str.ToString)
            Catch ex As Exception
            End Try
        End Sub
        ''' <summary>
        ''' Call in a callback to refresh the grid.  Pass in e.Output as the parameter.
        ''' </summary>
        Public Sub Refresh(ByVal data As HtmlTextWriter)
            lit.Text = HandleText()
            lit.RenderControl(data)
        End Sub
        Private Function HandleText() As String
            Dim order As New ArrayList
            Dim template As String = Me.ItemTemplate.Text
            While template.IndexOf("##DataItem(") > -1
                Dim EndIndex As Integer = template.IndexOf("')##")
                Dim StartIndex As Integer = template.IndexOf("##DataItem('") + 12
                order.Add(template.Substring(StartIndex, (EndIndex - StartIndex)))
                template = template.Substring(EndIndex + 4)
            End While
            If Not Page.IsPostBack Then
                Dim sb As New StringBuilder
                sb.Append("")
                Dim dr As IDataReader = Datasource
                dr.Read()
                Dim iCount As Integer = CInt(dr(0))
                Dim pageCount As Integer = CInt(Math.Ceiling(iCount / Me.PageSize))
                dr.NextResult()
                While dr.Read
                    Dim item As String
                    Dim ItemArray As New ArrayList
                    For Each item In order
                        ItemArray.Add(dr(item).ToString)
                    Next
                    Dim e As New ItemBoundEventArgs(ItemArray)
                    RaiseEvent ItemBound(Me, e)
                    For Each item In e.Item
                        sb.Append(item.ToString.Replace("#", String.Empty).Replace("""", String.Empty).Replace("\", "&#92;").Replace("|", "&#124;").Replace("^", "&#94;").Replace("'", "\'") & Me.ColDelimiter)
                    Next
                    sb.Remove((sb.Length - Me.ColDelimiter.Length), Me.ColDelimiter.Length)
                    sb.Append(Me.RowDelimiter)
                End While
                dr.Close()
                Return "<script>window." & Me.ClientID & ".data='" & sb.ToString & "';window." & Me.ClientID & ".PageCount=" & pageCount & ";</script>"
            Else
                Return String.Empty
            End If
        End Function
        Public Event Callback(ByVal sender As Object, ByVal e As CallBackEventArgs)
        Public Sub RaiseCallback(ByVal sender As Object, ByVal e As CallBackEventArgs) Handles cb.Callback ' Implements ICallbackEventHandler.RaiseCallback
            OnCallback(e)
        End Sub
        Protected Overridable Sub OnCallback(ByVal e As CallBackEventArgs)
            RaiseEvent Callback(cb, e)
        End Sub
        Private Sub ActiveGrid_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not Page.ClientScript.IsClientScriptIncludeRegistered("AMActiveGrid") Then
                Page.ClientScript.RegisterClientScriptInclude("AMActiveGrid", Page.ClientScript.GetWebResourceUrl(Me.GetType, "ActiveGrid.js"))
            End If
        End Sub
#End Region

    End Class

    Public Class ItemBoundEventArgs
        Inherits EventArgs
        Public Item As ArrayList
        Friend Sub New(ByVal sParam As ArrayList)
            Item = sParam
        End Sub
    End Class

    <ToolboxItem(False)> _
    Public Class ItemTemplateContents
        Inherits System.Web.UI.Control
        <DefaultValue(""), Browsable(False), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
        Public Property Text() As String
            Get
                If Me.Controls.Count > 0 AndAlso TypeOf Me.Controls(0) Is LiteralControl Then
                    Return DirectCast(Me.Controls(0), LiteralControl).Text
                End If
                Return ""
            End Get
            Set(ByVal value As String)
                Me.Controls.Clear()
                Me.Controls.Add(New LiteralControl(value))
            End Set
        End Property
    End Class
    Public Class ActiveGridDesigner
        Inherits ControlDesigner

        Public Overrides Function GetDesignTimeHtml() As String
            Return "<table cellpadding=""0"" cellspacing=""0"" width=""100%""><tr><td>Active Modules Grid Control<br />Please use source view to make changes</td></tr></table>"
        End Function

    End Class

End Namespace
